package commonRepository

import (
    "errors"
    commonError "gin_http/utils/common/error"

    "gorm.io/gorm"
)

type BaseRepository[T any] struct {
	DB *gorm.DB
}

func NewBaseRepository[T any](db *gorm.DB) *BaseRepository[T] {
	return &BaseRepository[T]{DB: db}
}

// Create 新增信息
func (r *BaseRepository[T]) Create(entity *T) error {
    if err := r.DB.Create(entity).Error; err != nil {
        return commonError.New(commonError.CodeDBInsertFailed, "新增信息失败", err)
    }
    return nil
}

// GetByID 根据主键查询
func (r *BaseRepository[T]) GetByID(id uint) (*T, error) {
	var entity T
    if err := r.DB.First(&entity, id).Error; err != nil {
        if err == gorm.ErrRecordNotFound {
            return nil, commonError.New(commonError.CodeRecordNotFound, "未查找到信息", err)
        }
        return nil, commonError.New(commonError.CodeDBQueryFailed, "查询信息失败", err)
    }
    return &entity, nil
}

// Update 更新信息
func (r *BaseRepository[T]) Update(entity *T) error {
    if err := r.DB.Save(entity).Error; err != nil {
        return commonError.New(commonError.CodeDBUpdateFailed, "更新信息失败", err)
    }
    return nil
}

// Delete 根据主键删除
func (r *BaseRepository[T]) Delete(id uint) error {
	var entity T
    if err := r.DB.Delete(&entity, id).Error; err != nil {
        return commonError.New(commonError.CodeDBDeleteFailed, "删除信息失败", err)
    }
    return nil
}

// FindBy 条件查询
func (r *BaseRepository[T]) FindBy(cond map[string]interface{}) ([]T, error) {
	var list []T
    if err := r.DB.Where(cond).Find(&list).Error; err != nil {
        return nil, commonError.New(commonError.CodeDBQueryFailed, "条件查询失败", err)
    }
    return list, nil
}

// FirstBy 条件查询第一条
func (r *BaseRepository[T]) FirstBy(cond map[string]interface{}) (*T, *commonError.Error) {
	var entity T
    if err := r.DB.Where(cond).First(&entity).Error; err != nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            return nil, commonError.New(commonError.CodeRecordNotFound, "未查找到信息", err)
        }
        return nil, commonError.New(commonError.CodeDBQueryFailed, "查询信息失败", err)
    }
    return &entity, nil
}

// FindPage 分页查询
func (r *BaseRepository[T]) FindPage(offset, limit int, cond map[string]interface{}) ([]T, error) {
	var list []T
	query := r.DB.Model(new(T))
	if cond != nil {
		query = query.Where(cond)
	}
    if err := query.Offset(offset).Limit(limit).Find(&list).Error; err != nil {
        return nil, commonError.New(commonError.CodeDBQueryFailed, "分页查询失败", err)
    }
    return list, nil
}

// Count 统计数量
func (r *BaseRepository[T]) Count(cond map[string]interface{}) (int64, error) {
	var count int64
	query := r.DB.Model(new(T))
	if cond != nil {
		query = query.Where(cond)
	}
    if err := query.Count(&count).Error; err != nil {
        return 0, commonError.New(commonError.CodeDBQueryFailed, "统计数量失败", err)
    }
    return count, nil
}
